﻿/*
 * 【作者】郝伟老师
 * 【使用】日志数据类。
 * 【说明】 
 * 日志信息类，格式为：时间|类型|位置|数据列表，其中
 * 时间：格式为 2019/06/14 09:45:46
 * 类型：格式为整型，可以自定义
 * 位置：表示日志发生的位置信息，如 WindGoes6.Data.Logs.cs@Line32
 * 数据列表：字符串列表，如 "1, 342, Version”
 * 
 * 所有的分隔符为 (char)6，如果有换行符，替换为"a@c3k_K4.X@a-3;p"
 * 
 * 
 * 【历史更新记录】
 * 2019/06/14   V1.0    初步建立此类。 
 * 
 * 
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindGoes6.Data.Logs
{
    /// <summary>
    /// 日志信息类，格式为：时间|类型|位置信息|数据列表
    /// </summary>
    public class Log
    {
        /// <summary>
        /// 日志时间。Recoding time.
        /// </summary>
        public DateTime Time { get; set; } = DateTime.Now;

        /// <summary>
        /// 日志类型。The type of the log.
        /// </summary>
        public int LogType { get; set; }

        /// <summary>
        /// Full class name + method name, such as HWLogViewer.Log.Parse
        /// </summary>
        public string MethodName { get; set; }

        /// <summary>
        /// 日志数据列表。Arguements of a log.
        /// </summary>
        public string[] Arguments { get; set; }

        // Used to separate data fields of a log when serializing.
        static char separator = (char)6;
        // to replace \n with this
        static string lineBreaker = "a@c3k_K4.X@a-3;p";
        // start time to compare with
        static DateTime startTime = new DateTime(2019, 1, 1);

 

        public Log()
        {
            LogType = 0;
            MethodName = "None";
            Arguments = new string[0];
        }




        public Log(int logType, string[] args)
        {
            LogType = logType;
            Arguments = args;
        }


        public Log(int type, string methodName, params string[] args)
        {
            LogType = type;
            MethodName = methodName;
            Arguments = args;
        }


        /// <summary>
        /// Load a list of logs from a log file.
        /// </summary>
        /// <param name="logfile">The input log file.</param>
        /// <returns></returns>
        public static List<Log> LoadFromFile(string logfile)
        {
            List<Log> logs = new List<Log>();
            if (File.Exists(logfile))
            {
                foreach (string line in File.ReadAllLines(logfile))
                {
                    if (line.Trim().Length == 0)
                        continue;

                    Log log = Log.Parse(line);
                    if (log != null)
                        logs.Add(log);
                }
            }

            return logs;
        }

        /// <summary>
        /// To a string array: {time, log type, method name, arguments} 
        /// </summary>
        /// <returns></returns>
        public string[] ToStrings()
        {
            string[] data = new string[Arguments.Length + 3];
            data[0] = this.Time.ToString("yyyy/MM/dd HH:mm:ss");
            data[1] = this.LogType.ToString();
            data[2] = this.MethodName;
            for (int i = 0; i < Arguments.Length; i++)
                data[i + 3] = Arguments[i];
            return data;
        }

        /// <summary>
        /// Format: yyyyMMddHHmmss|LogType|Arguments.
        /// Note: "\r\n" or "\n" --> "a@c3k_K4.X@a-3;p"
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append((int)(Time - startTime).TotalSeconds);
            sb.Append(separator);
            sb.Append((int)LogType);
            sb.Append(separator);
            sb.Append(MethodName);
            sb.Append(separator);
            if (Arguments != null && Arguments.Length > 0)
                sb.Append(string.Join(separator.ToString(), Arguments));
            return sb.ToString().Replace("\r", "").Replace("\n", lineBreaker);
        }

        /// <summary>
        /// Parses a string into a Log object. If the format of input string is incorrect, returns null.
        /// </summary>
        /// <param name="str">Input string.</param>
        /// <returns></returns>
        public static Log Parse(string str)
        {
            Log log = null;

            try
            {
                string[] data = str.Replace(lineBreaker, "\r\n").Split(separator);
                log = new Log();
                log.Time = startTime.AddSeconds(int.Parse(data[0]));
                log.LogType = int.Parse(data[1]);
                log.MethodName = data[2];
                log.Arguments = new string[data.Length - 3];
                for (int i = 0; i < log.Arguments.Length; i++)
                    log.Arguments[i] = data[i + 3];
            }
            catch { }


            return log;
        }


    }

}
